#include "mainwindow.h"
#include "./ui_mainwindow.h"

#include "CommonButton.hpp"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

 /*
 * Отображение страницы авторизации
 */
    ui->main_stack->setCurrentIndex(0);

 /*
 * Инициализация интерфейса управления
 */
    taskInit();
    task_state = 0;
    ctl_state = 0;

    ui->stop_button->setEnabled(false);
    ui->resum_button->setEnabled(false);

    ui->telemRpm7_val->setVisible(false);
    ui->telemRpm8_val->setVisible(false);
    ui->telemRpm7->setVisible(false);
    ui->telemRpm8->setVisible(false);

/*
 * Инициализация внешнего канала управления
 */
  external_cmd_sock = external_start();
/*
 * Подготовка канала телеметрии
 */
    ftc_tlm_init(&tlm.ftc_tlm);
    tlm_sock = tlm_start();

    fc_tlm_init(&tlm.fc_tlm);
    ftc_tlm_init(&tlm.ftc_tlm);
    bc_tlm_init(&tlm.bc_tlm);
    QLabel* acts_val[MAX_ACTUATORS_COUNT] = {
        ui->telemRpm1_val
        ,ui->telemRpm2_val
        ,ui->telemRpm3_val
        ,ui->telemRpm4_val
        ,ui->telemRpm5_val
        ,ui->telemRpm6_val
        ,ui->telemRpm7_val
        ,ui->telemRpm8_val
    };
    for(auto i : acts_val)
        i->setNum(0);

/*
 * Запуск главного таймера
 */
    timer = new QTimer();
    connect(timer, SIGNAL(timeout()), this, SLOT(slotTimerAlarm()));
    timer->start(500);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::ctlConnector()
{
    if(ctl_state == 0){
        //std::cout << "Запрос соединения.\n";
        // Запрос соединения если оно не установлено
        if(ctl_connect(&ctl_sock) != -1)
            ctl_state = 1;

    }else{
        //std::cout << "Проверка соединения.\n";
        // Проверка работоспособности соединения
        if(ctl_con_check(ctl_sock) == -1){
            ctl_state = 0;
            ctl_con_close(ctl_sock);
            std::cout << "Завершение соединения.\n";
        }

    }
}

void MainWindow::telemHandler()
{
    recv_tlm(tlm_sock, &tlm);
    task_state = tlm.ftc_tlm.state_flg;
    switch(task_state){
    case STATE_INIT:
      ui->taskStart_button->setEnabled(true);
      ui->interrupt_button->setEnabled(false);
      ui->stop_button->setEnabled(false);
      ui->resum_button->setEnabled(false);
      break;

    case STATE_TAKEOFF:
      ui->taskStart_button->setEnabled(false);
      ui->interrupt_button->setEnabled(true);
      ui->stop_button->setEnabled(true);
      ui->resum_button->setEnabled(false);
      break;

    case STATE_STOP:
      ui->taskStart_button->setEnabled(false);
      ui->interrupt_button->setEnabled(true);
      ui->stop_button->setEnabled(false);
      ui->resum_button->setEnabled(true);
      break;

    case STATE_RESUM:
      ui->taskStart_button->setEnabled(false);
      ui->interrupt_button->setEnabled(true);
      ui->stop_button->setEnabled(true);
      ui->resum_button->setEnabled(false);
      break;

    default:
      ui->taskStart_button->setEnabled(false);
      ui->interrupt_button->setEnabled(true);
      ui->stop_button->setEnabled(false);
      ui->resum_button->setEnabled(false);
      break;
    }

    if(tlm.fc_tlm.lat < 1e-5 || tlm.fc_tlm.gps_fix < 2)
      ui->telemLat_val->setNum(0);
    else
      ui->telemLat_val->setNum(tlm.fc_tlm.lat);

    if(tlm.fc_tlm.lon < 1e-5 || tlm.fc_tlm.gps_fix < 2)
      ui->telemLon_val->setNum(0);
    else
      ui->telemLon_val->setNum(tlm.fc_tlm.lon);

    // Высота, м
    ui->telemHight_val->setNum(tlm.fc_tlm.hight);
    // Скорость, м/c
    ui->telemSpeed_val->setNum(tlm.fc_tlm.speed);
    // Температура, C
    ui->telemTemperature_val->setNum(tlm.bc_tlm.temperature);

    // Обороты, об/мин
    QLabel* acts_val[MAX_ACTUATORS_COUNT] = {
         ui->telemRpm1_val
        ,ui->telemRpm2_val
        ,ui->telemRpm3_val
        ,ui->telemRpm4_val
        ,ui->telemRpm5_val
        ,ui->telemRpm6_val
        ,ui->telemRpm7_val
        ,ui->telemRpm8_val
    };
    for(int i = 0; i < tlm.fc_tlm.actuators_count; ++i){
      double val = pwm_convert(tlm.fc_tlm.actuators[i]);
      acts_val[i]->setText(QString::number(val, 'f', 2));
    }

    // Таймер начала взлета
    ui->telemTimerStart_val->setText(QTime::fromMSecsSinceStartOfDay(tlm.ftc_tlm.timer_1*1000).toString("hh:mm:ss"));

    // Таймер начала посадки
    int tmp = tlm.ftc_tlm.timer_2;
    QString timer_2_str;
    if(tmp >= 86400)
        timer_2_str = "01:" + QTime::fromMSecsSinceStartOfDay((tmp - 86400)*1000).toString("hh:mm:ss");
    else
        timer_2_str = QTime::fromMSecsSinceStartOfDay(tmp*1000).toString("hh:mm:ss");
    ui->telemTimerFinish_val->setText(timer_2_str);

    // Соединение (Да/Нет)
    if (ctl_state == 1){
        ui->telemConnect_val->setText(static_cast<QString>("Да"));

        if(task_state == 0){
            ui->taskStart_button->setEnabled(true);
            ui->interrupt_button->setEnabled(false);
        }else{
            ui->taskStart_button->setEnabled(false);
            ui->interrupt_button->setEnabled(true);
        }
    }else{
        ui->telemConnect_val->setText(static_cast<QString>("Нет"));
        ui->taskStart_button->setEnabled(false);
        ui->interrupt_button->setEnabled(false);
    }

  // Обработка failsafes
  int cur_time = static_cast<int>(std::time(nullptr));
  if(     tlm.fc_tlm.fail.time != 0
      &&  tlm.fc_tlm.fail.time + 2 >= cur_time
      &&  tlm.fc_tlm.fail.time != last_fail_time){
    //std::cout << "Type:\t" << tlm.fc_tlm.fail.type << "\n";
    last_fail_time = tlm.fc_tlm.fail.time;

    switch (tlm.fc_tlm.fail.type){
    case FAIL_GPS:
      fail_buff = " / Потерян сигнал СНС";
      break;
    case FAIL_BATTERY:
      fail_buff = " / Потеря питания";
      break;
    case FAIL_MOTOR:
      fail_buff = " / Потеря двигателя";
      break;
    case FAIL_POWER:
      fail_buff = " / Потеря основного питания";
      break;
    case FAIL_UNKNOWN:
      fail_buff = " / Ошибка бортовой системы управления";
      break;
    default:
      break;
    }
  }

  // Консоль отладки
  EVENT_t new_event = tlm.ftc_tlm.event;
  if(last_event != new_event && new_event < EVENT_MAX){
    if(alarm_buff.size() > 1024){
      while(alarm_buff.at(0) != '\n')
    //alarm_buff.erase(alarm_buff.cbegin());
        alarm_buff = alarm_buff.right(alarm_buff.size()-1);
      //alarm_buff.erase(alarm_buff.cbegin());
      alarm_buff = alarm_buff.right(alarm_buff.size()-1);
    }
    alarm_buff += QDateTime::currentDateTime().toString("hh:mm:ss");
    alarm_buff += "\t";
    alarm_buff += alarms.at(static_cast<int>(new_event));
    alarm_buff += fail_buff;
    alarm_buff += "\n";
    ui->textEdit->setText(alarm_buff);
    last_event = new_event;

    fail_buff.clear();

    ui->textEdit->verticalScrollBar()->setValue(ui->textEdit->verticalScrollBar()->maximum());
  }

}

void MainWindow::taskInit()
{
    ui->taskStart_button->setEnabled(false);
    ui->interrupt_button->setEnabled(false);
}

// Сигналы
void MainWindow::slotTimerAlarm()
{
    telemHandler();
    ctlConnector();
    external_cmds_handler();
}

void MainWindow::on_taskStart_button_clicked()
{
    flight_task_t tsk;
    // Высота, м
    tsk.hight = ui->taskHight_val->displayText().toInt();
    // Время старта от начала дня, сек
    tsk.start_time = ui->taskStartTime_val->time().msecsSinceStartOfDay() / 1000;
    // Время полета, сек
    tsk.hang_time = ui->taskFlightTime_val->time().msecsSinceStartOfDay() / 1000;
    if(ui->plusDay->isChecked())
        tsk.hang_time += 86400;

    // Блокировка по высоте и времени зависания
    if(     tsk.hight == 0
        ||  tsk.hang_time == 0
        ||  tsk.hight > 100
        ||  tsk.hang_time > 172800)
        return;

    CTL_COMMAND_t cmd = CTL_TASK;
    send_cmd(ctl_sock, &cmd);
    send_task(ctl_sock, &tsk);
}

void MainWindow::on_interrupt_button_clicked()
{
    CTL_COMMAND_t cmd = CTL_INTERRUPT;
    send_cmd(ctl_sock, &cmd);
}

void MainWindow::on_stop_button_clicked()
{
    CTL_COMMAND_t cmd = CTL_STOP;
    send_cmd(ctl_sock, &cmd);
}

void MainWindow::on_resum_button_clicked()
{
    CTL_COMMAND_t cmd = CTL_RESUM;
    send_cmd(ctl_sock, &cmd);
}

void MainWindow::on_pass_val_returnPressed()
{
  QString LOGIN = "admin";
  QString PASS = "1234";

  QString login = ui->login_val->text();
  QString pass = ui->pass_val->text();

  if(login == LOGIN && pass == PASS)
    ui->main_stack->setCurrentIndex(1);
}

double MainWindow::pwm_convert(int pwm){
  const int PWM_MIN = 1100;
  const int PWM_MAX = 1900;

  if(pwm <= PWM_MIN)
    return 0;
  if(pwm >= PWM_MAX)
    return 100;

  return static_cast<double>(pwm - PWM_MIN) * 100 / (PWM_MAX - PWM_MIN);
}

void MainWindow::external_cmds_handler(){
  CTL_COMMAND_t cmd = static_cast<CTL_COMMAND_t>(-1);

  char byte = -1;
  recv_external_cmd(external_cmd_sock, &byte);

  if(byte != -1){
    cmd = static_cast<CTL_COMMAND_t>(byte - '0');
    //std::cout << cmd << " <- \n";
  }

  switch(cmd){
  case CTL_TASK:
    on_taskStart_button_clicked();
    break;
  case CTL_INTERRUPT:
    on_interrupt_button_clicked();
    break;
  case CTL_STOP:
    on_stop_button_clicked();
    break;
  case CTL_RESUM:
    on_resum_button_clicked();
    break;
  default:
    break;
  }
}
